package com.efounder.message.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.efounder.message.struct.IMStruct002;
import com.efounder.util.AppContext;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import net.sf.json.JSON;
import net.sf.json.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class MessageDBManager {
    private SQLiteDatabase db;
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault());
    private MessageDBHelper helper;
    private static MessageDBManager manager;
    private Gson gson2 = new GsonBuilder().enableComplexMapKeySerialization().create();
    private static final String TAG = "MessageDBManager";

    //重写deserialize方法的gson，防止int存为double
//    private Gson gson = new GsonBuilder()
//            .registerTypeAdapter(
//                    new TypeToken<TreeMap<String, Object>>() {
//                    }.getType(),
//                    new JsonDeserializer<TreeMap<String, Object>>() {
//                        @Override
//                        public TreeMap<String, Object> deserialize(
//                                JsonElement json, Type typeOfT,
//                                JsonDeserializationContext context) throws JsonParseException {
//
//                            TreeMap<String, Object> treeMap = new TreeMap();
//                            JsonObject jsonObject = json.getAsJsonObject();
//                            Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
//                            for (Map.Entry<String, JsonElement> entry : entrySet) {
//                                treeMap.put(entry.getKey(), entry.getValue());
//                            }
//                            return treeMap;
//                        }
//                    }).create();

    public MessageDBManager() {
        helper = new MessageDBHelper(AppContext.getInstance());
        this.db = helper.getWritableDatabase();
    }

    public static MessageDBManager getInstance() {
        if (manager == null) {
            manager = new MessageDBManager();
        }
        return manager;
    }

    public SQLiteDatabase getDb() {
        return db;
    }

    public long insert(IMStruct002 struct002) {
        ContentValues values = this.getContentValues(struct002);
        return this.db.insertWithOnConflict("message", (String) null, values, 5);
    }

    public void insert(List<IMStruct002> struct002List) {
        this.db.beginTransaction();
        Iterator var3 = struct002List.iterator();

        while (var3.hasNext()) {
            IMStruct002 struct002 = (IMStruct002) var3.next();
            this.insert(struct002);
        }

        this.db.setTransactionSuccessful();
        this.db.endTransaction();
    }

    public int update(IMStruct002 struct002) {
        ContentValues values = this.getContentValues(struct002);
        String whereClause = "msgID=? and toUserType=? and toUserId=? and time=? and fromUserId=?";
        String[] whereArgs = new String[]{String.valueOf(struct002.getMessageID()), String.valueOf(struct002.getToUserType()), String.valueOf(struct002.getToUserId()), String.valueOf(values.get("time")), String.valueOf(struct002.getFromUserId())};
        return this.db.update("message", values, whereClause, whereArgs);
    }

    public void update(List<IMStruct002> struct002List) {
        this.db.beginTransaction();
        Iterator var3 = struct002List.iterator();

        while (var3.hasNext()) {
            IMStruct002 struct002 = (IMStruct002) var3.next();
            this.update(struct002);
        }

        this.db.setTransactionSuccessful();
        this.db.endTransaction();
    }

    public int delete(IMStruct002 struct002) {
        this.db.execSQL("update message set enable = 0 where msgID =\'" + struct002.getMessageID() + "\'");
        return 1;
    }

    public int delete(String msgID) {
        this.db.execSQL("update message set enable = 0 where msgID =\'" + msgID + "\'");
        return 1;
    }

    public int setEnable(IMStruct002 struct002) {
        int enable = struct002.isEnable() ? 1 : 0;
        this.db.execSQL("update message set enable =" + enable + " where msgID =\'" + struct002.getMessageID() + "\'");
        return 1;
    }

    public void delete(List<IMStruct002> struct002List) {
        this.db.beginTransaction();
        Iterator var3 = struct002List.iterator();

        while (var3.hasNext()) {
            IMStruct002 struct002 = (IMStruct002) var3.next();
            this.delete(struct002);
        }

        this.db.setTransactionSuccessful();
        this.db.endTransaction();
    }

    //获取收到的最后一条消息的时间
    public IMStruct002 getLastReceiveMessage() {
        String sql = "select * from message where servertime=(select max(servertime) from  message where enable =1)";
        List list = this.query(sql);
        return list.size() == 0 ? null : (IMStruct002) list.get(0);
    }

    //更新消息状态
    public void updateMessageState(String msgID, int state) {
        this.db.execSQL("update message set state =" + state + " where msgID =\'" + msgID + "\'");
    }

    //更改消息为撤回
    public void updateMessage2Recall(String msgID, boolean isRecall) {
//        this.db.execSQL("update message set isRecall =1  where msgID =\'" + msgID + "\'");
        int reacll = isRecall ? 1 : 0;
        this.db.execSQL("update message set isRecall =?  where msgID =? ", new Object[]{reacll, msgID});

    }

    //更改消息为撤回
    public void updateMessage2Recall(IMStruct002 imStruct002, boolean isRecall) {
        updateMessage2Recall(imStruct002.getMessageID(), isRecall);
    }

    //执行sql
    public void excuteSql(String sql) {
        try {
            this.db.execSQL(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //根据ID 查询消息
    public IMStruct002 queryForID(String msgID) {
        String sql = "select * from message where msgID=\'" + msgID + "\'";
        List list = this.query(sql);
        return list.size() == 0 ? null : (IMStruct002) list.get(0);
    }

    public List<IMStruct002> queryPersonalLessThan(int fromUserId, int toUserId, int msgNum) {
        return this.queryPersonalLessThan(fromUserId, toUserId, (String) null, msgNum);
    }


    /**
     * 查询两个msgID之间的数据
     *
     * @param fromUserId 发送人（我）
     * @param toUserId   接收人
     * @param topMsgID   顶部消息id
     * @param lastMsgID  后面的msgID
     * @return
     */
    public List<IMStruct002> queryPersonalBetween(int fromUserId, int toUserId, String topMsgID, String lastMsgID) {
        StringBuffer subSql = new StringBuffer();
        StringBuffer whereString = new StringBuffer(" where ((fromUserId=" + fromUserId + " and toUserId=" + toUserId + " and toUserType=0) or (fromUserId=" + toUserId + " and toUserId=" + fromUserId + " and toUserType=0)  or ( fromUserId=" + toUserId + " and toUserId=" + toUserId + " and toUserType=2)) and messageChildType<100 and enable=1");
        if (topMsgID != null) {
            whereString.append(" and localTime < (select localTime from message where msgID =\'" + topMsgID + "\'" + ")  ");
        }
        if (lastMsgID != null) {
            whereString.append(" and localTime > (select localTime from message where msgID =\'" + lastMsgID + "\'" + ")  ");
        }
        subSql.append(" select * from message " + whereString);
        subSql.append(" order by localTime asc");
//        subSql.append(" limit ( select count(*)-" + msgNum + " num from message " + whereString);
//        subSql.append(" )," + msgNum + " ");
        String sql = subSql.toString();
        Log.d("sql", "sql-----queryPersonalBetween------\n" + sql);
        return this.query(sql, (String[]) null);
    }

    /**
     * 查询msgID之前的消息
     *
     * @param fromUserId 发送人（我）
     * @param toUserId   接收人
     * @param msgID      消息id
     * @param msgNum     查询的数量
     * @return
     */
    public List<IMStruct002> queryPersonalLessThan(int fromUserId, int toUserId, String msgID, int msgNum) {
        StringBuffer subSql = new StringBuffer();
        StringBuffer whereString = new StringBuffer(" where ((fromUserId=" + fromUserId + " and toUserId=" + toUserId + " and toUserType=0) or (fromUserId=" + toUserId + " and toUserId=" + fromUserId + " and toUserType=0)  or ( fromUserId=" + toUserId + " and toUserId=" + toUserId + " and toUserType=2)) and messageChildType<100 and enable=1");
        if (msgID != null) {
            whereString.append(" and localTime < (select localTime from message where msgID =\'" + msgID + "\'" + ")  ");
        }

        subSql.append(" select * from message " + whereString);
        subSql.append(" order by localTime asc");
        subSql.append(" limit ( select count(*)-" + msgNum + " num from message " + whereString);
        subSql.append(" )," + msgNum + " ");
        String sql = subSql.toString();
        Log.d("sql", "sql-----queryPersonalLessThan------\n" + sql);
        return this.query(sql, (String[]) null);
    }

    public List<IMStruct002> queryGroupLessThan(int groupToUserId, int msgNum) {
        return this.queryGroupLessThan(groupToUserId, (String) null, msgNum);
    }

    public List<IMStruct002> queryGroupLessThan(int groupToUserId, String msgID, int msgNum) {
        StringBuffer subSql = new StringBuffer();
        StringBuffer whereString = new StringBuffer(" where toUserId=" + groupToUserId + " and toUserType=1 and messageChildType<100 and enable=1");
        if (msgID != null) {
            whereString.append(" and localTime < (select localTime from message where msgID =\'" + msgID + "\'" + ")  ");
        }

        subSql.append(" select * from message " + whereString);
        subSql.append(" order by localTime asc");
        subSql.append(" limit ( select count(*)-" + msgNum + " num from message " + whereString);
        subSql.append(" )," + msgNum + " ");
        String sql = subSql.toString();
        Log.d("sql", "sql-----queryGroupLessThan------\n" + sql);
        return this.query(sql, (String[]) null);
    }

    public List<IMStruct002> query(String sql) {
        return this.query(sql, (String[]) null);
    }

    public List<IMStruct002> query(String sql, String[] selectionArgs) {
        ArrayList list = new ArrayList();
        Cursor cursor = this.db.rawQuery(sql, selectionArgs);

        while (cursor.moveToNext()) {
            IMStruct002 struct002 = new IMStruct002();
            struct002.setMsgId(cursor.getInt(cursor.getColumnIndex("messageId")));
            struct002.setMessageID(cursor.getString(cursor.getColumnIndex("msgID")));
            struct002.setFromUserId(cursor.getInt(cursor.getColumnIndex("fromUserId")));
            struct002.setToUserId(cursor.getInt(cursor.getColumnIndex("toUserId")));

            try {
                Date var71 = this.dateFormat.parse(cursor.getString(cursor.getColumnIndex("time")));
                struct002.setTime(var71.getTime());
                Date localTime;
                if (cursor.getString(cursor.getColumnIndex("serverTime")) != null) {
                    localTime = this.dateFormat.parse(cursor.getString(cursor.getColumnIndex("serverTime")));
                    struct002.setServerTime(localTime.getTime());
                } else if (cursor.getString(cursor.getColumnIndex("time")).length() == 10) {
                    var71 = this.dateFormat.parse(cursor.getString(cursor.getColumnIndex("time")) + "000");
                    struct002.setServerTime(var71.getTime());
                } else {
                    struct002.setServerTime(var71.getTime());
                }

                if (cursor.getString(cursor.getColumnIndex("localTime")) != null) {
                    localTime = this.dateFormat.parse(cursor.getString(cursor.getColumnIndex("localTime")));
                    struct002.setLocalTime(localTime.getTime());
                } else if (cursor.getString(cursor.getColumnIndex("time")).length() == 10) {
                    var71 = this.dateFormat.parse(cursor.getString(cursor.getColumnIndex("time")) + "000");
                    struct002.setLocalTime(var71.getTime());
                } else {
                    struct002.setLocalTime(var71.getTime());
                }
            } catch (ParseException var8) {
                var8.printStackTrace();
            }

            struct002.setToUserType((byte) cursor.getInt(cursor.getColumnIndex("toUserType")));
            struct002.setMessageChildType((short) cursor.getInt(cursor.getColumnIndex("messageChildType")));
            struct002.setBody(cursor.getBlob(cursor.getColumnIndex("body")));
            struct002.setState(cursor.getInt(cursor.getColumnIndex("state")));
            struct002.setReadState(cursor.getInt(cursor.getColumnIndex("readState")));
            struct002.setVersion(cursor.getShort(cursor.getColumnIndex("version")));
            struct002.setpMsgId(cursor.getString(cursor.getColumnIndex("pMsgId")));
            struct002.setpUserId(cursor.getInt(cursor.getColumnIndex("pUserId")));
            struct002.setEnable(cursor.getInt(cursor.getColumnIndex("enable")) == 1);
            struct002.setRecall(cursor.getInt(cursor.getColumnIndex("isRecall")) == 1);

            String extra = cursor.getString(cursor.getColumnIndex("extra"));

            if (extra != null && !"".equals(extra) && !"{}".equals(extra)) {
                try {
                    Map<String, Object> extraMap1 = JSONObject.fromObject(extra);
                    HashMap<String, Object> extraMap = new HashMap<>();
                    for (String key : extraMap1.keySet()) {
                        if (extraMap1.get(key) instanceof JSON) {
                            extraMap.put(key, extraMap1.get(key).toString());
                        } else {
                            extraMap.put(key, extraMap1.get(key));
                        }
                    }
                    struct002.setExtMap(extraMap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            list.add(struct002);
        }

        cursor.close();
        return list;
    }

//    /**
//     * 将JSONObjec对象转换成Map-List集合
//     * @param json
//     * @return
//     */
//    public static Map<String, Object> toMap(JsonObject json){
//        Map<String, Object> map = new HashMap<String, Object>();
//        Set<Map.Entry<String, JsonElement>> entrySet = json.entrySet();
//        for (Iterator<Map.Entry<String, JsonElement>> iter = entrySet.iterator(); iter.hasNext(); ){
//            Map.Entry<String, JsonElement> entry = iter.next();
//            String key = entry.getKey();
//            Object value = entry.getValue();
//            if(value instanceof JsonArray)
//                map.put((String) key, toList((JsonArray) value));
//            else if(value instanceof JsonObject)
//                map.put((String) key, toMap((JsonObject) value));
//            else
//                map.put((String) key, value);
//        }
//        return map;
//    }

    private ContentValues getContentValues(IMStruct002 struct002) {
        ContentValues values = new ContentValues();
        values.put("messageId", Integer.valueOf(struct002.getMsgId()));
        values.put("msgID", struct002.getMessageID());
        values.put("fromUserId", Integer.valueOf(struct002.getFromUserId()));
        values.put("toUserId", Integer.valueOf(struct002.getToUserId()));
        values.put("time", (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())).format(new Date(struct002.getTime())));
        values.put("serverTime", (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())).format(new Date(struct002.getServerTime())));
        values.put("localTime", (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())).format(new Date(struct002.getLocalTime())));
        values.put("toUserType", Byte.valueOf(struct002.getToUserType()));
        values.put("messageChildType", Short.valueOf(struct002.getMessageChildType()));
        values.put("body", struct002.getBody());
        values.put("state", Integer.valueOf(struct002.getState()));
        values.put("readState", Integer.valueOf(struct002.getReadState()));
        values.put("enable", Integer.valueOf(struct002.isEnable() ? 1 : 0));
        values.put("version", Integer.valueOf(struct002.getVersion()));
        values.put("pMsgId", struct002.getpMsgId());
        values.put("pUserId", Integer.valueOf(struct002.getpUserId()));
        values.put("bodyString", struct002.getBodyString() == null ? "" : struct002.getBodyString());
        values.put("isRecall", struct002.isRecall() == true ? 1 : 0);

        Map<String, Object> extraMap = struct002.getExtMap();

        if (extraMap == null) {
            values.put("extra", "");
        } else {
            try {
                values.put("extra", gson2.toJson(extraMap));
            } catch (Exception e) {
                e.printStackTrace();
                values.put("extra", "");
                Log.e(TAG, "getContentValues: map转json失败");
            }
        }

        return values;
    }


    public void release() {
        if (helper != null) {
            helper.close();
        }
        manager = null;

    }
}
